import datetime
import random
import time
import django
import requests
import json
import os
from django.utils import timezone

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'gas_recycler_server.settings')
django.setup()

from SensorMonitor.modules import ExceptionPrinter
from SensorMonitor.models import Device, Data, Datapack

configPath = "/home/gas_recycler_server/SensorMonitor/modules/data_getter_config.json"
tz = timezone.get_current_timezone()

with open(configPath, "r") as configFile:
	config = json.loads(configFile.read())
	configFile.close()


class Keys:
	headers = 'headers'
	login = 'login'
	urls = 'urls'
	userName = 'userName'
	password = 'password'
	getDevices = 'getDevices'
	params = 'params'
	getData = 'getData'
	deviceNumber = 'deviceNumber'
	cookie = 'cookie'
	cookieGenTime = 'cookieGenerateTime'
	cookieTimeout = 'cookieTimeout'
	datetimeFormat = 'datetimeFormat'


class RespKeys:
	productID = 'id'
	deviceNumber = 'deviceNumber'
	deviceName = 'name'
	isOnline = 'onLineState'
	createTime = 'creatTime'
	lastActiveTime = 'time'
	dimensions = 'type'

	unit = 'unit'
	dataName = 'name'
	templateId = 'templateId'
	value = 'value'
	dataTime = 'dataTime'


# min = 'min'
# max = 'max'


def printException(e):
	ExceptionPrinter.printException(e)


def str2datetime(timeStr):
	dt = datetime.datetime.strptime(timeStr, config[Keys.datetimeFormat])
	return dt.replace(tzinfo=tz)


class DataGetter:
	cookies = None

	def __init__(self):
		if config[Keys.cookie] == "" or time.time() - config[Keys.cookieGenTime] > config[Keys.cookieTimeout]:
			self.login()
		else:
			self.cookies = config[Keys.cookie]

	def login(self):
		# 定义请求头
		headers = config[Keys.headers][Keys.login]
		# 定义请求体
		data = {
			Keys.userName: config[Keys.userName],
			Keys.password: config[Keys.password]
		}
		try:
			# 发送请求,获取响应
			response = requests.post(config[Keys.urls][Keys.login], data=data, headers=headers)
			print("[STATUS]:", response.status_code, response.reason)
			# 解析响应
			if response.status_code == 200:
				if isinstance(response.cookies.values(), list):
					# 提取用户凭据
					self.cookies = response.cookies.values()[0]
					config[Keys.cookie] = self.cookies
					config[Keys.cookieGenTime] = time.time()
					# 记录用户凭据
					with open(configPath, 'w') as configFile:
						configFile.write(json.dumps(config, indent=4))
						configFile.close()
					print("[CONFIG]:", "Cookie updated.")
				print("[TEXT]:", response.text)
				print("[COOKIES]:", self.cookies)
				return True
		except Exception as e:
			printException(e)
			return False

	def getDevices(self):
		# 创建请求头
		headers = config[Keys.headers][Keys.getDevices]
		# 添加用户凭据
		headers['Cookie'] = "JSESSIONID=" + self.cookies
		# 创建请求参数
		params = config[Keys.params][Keys.getDevices]
		params['_'] = int(round(time.time() * 1000))
		# 提取API
		url = config[Keys.urls][Keys.getDevices]
		try:
			# 发送请求,获取响应
			response = requests.get(url, params=params, headers=headers)
			print("[STATUS]:", response.status_code, response.reason)
			# 解析响应
			if response.status_code == 200:
				print("[TEXT]:", response.text)
				print("[COOKIES]:", self.cookies)
				# 提取设备信息
				responseData = json.loads(response.text)['data']
				deviceCount = len(responseData)
				for i in range(0, deviceCount):
					respData_i = responseData[i]
					# 创建数据模型对象
					try:
						device = Device.objects.get(device_number__exact=respData_i[RespKeys.deviceNumber])
					except Data.DoesNotExist:
						device = Device()

					device.product_id = respData_i[RespKeys.productID]
					device.device_number = respData_i[RespKeys.deviceNumber]
					device.name = respData_i[RespKeys.deviceName]
					device.is_online = (respData_i[RespKeys.isOnline] == 1)
					device.create_time = str2datetime(respData_i[RespKeys.createTime])
					device.last_active_time = str2datetime(respData_i[RespKeys.lastActiveTime])
					device.dimensions = respData_i[RespKeys.dimensions].replace(' ', '').replace('/', ',')
					# 存储入库
					device.save()
				return True
			return False
		except Exception as e:
			printException(e)
			return False

	def getDemoData(self, deviceNumber):
		try:
			now = datetime.datetime.now(tz=tz)
			datapack = Datapack()
			datapack.time = now
			datapack.device = Device.objects.get(device_number__exact=deviceNumber)
			datapack.hash = hash(datapack.__str__())
			datapack.save()

			for i in range(0, 5):
				data = Data()
				data.unit = ""
				if i == 0:
					if deviceNumber == "0F44178BF214":
						data.name = "甲烷"
					elif deviceNumber == "0F44178BF780":
						data.name = "硫化氢"
					data.unit = "%"
				elif i == 1:
					data.name = "信号强度"
					data.unit = "RSSI"
				else:
					data.name = "示例数据" + str(i)

				data.value = (now.minute / 60) * 90 + random.randint(-5, 5)
				data.time = now
				data.hash = hash(data.__str__())
				data.datapack = datapack
				data.device = Device.objects.get(device_number__exact=deviceNumber)
				data.save()
			return True
		except Exception as e:
			printException(e)
			return False

	def getData(self, deviceNumber):
		# 创建请求头
		headers = config[Keys.headers][Keys.getData]
		# 加入用户凭据
		headers['Cookie'] = "JSESSIONID=" + self.cookies
		# 创建请求参数
		data = {
			Keys.deviceNumber: deviceNumber
		}
		try:
			# 发送请求，等待响应
			response = requests.post(config[Keys.urls][Keys.getData], data=data, headers=headers)
			print("[STATUS]:", response.status_code, response.reason)
			# 解析响应
			if response.status_code == 200:
				print("[TEXT]:", response.text)
				print("[COOKIES]:", self.cookies)
				# 提取传感器数据
				responseData = json.loads(response.text)['datas']
				# 计算数据包的哈希值
				datapackHash = hash(response.text)
				dataCount = len(responseData)
				# 根据哈希值检索数据包
				datapack = Datapack.objects.filter(hash__exact=datapackHash)
				# 若存在检索结果,则直接返回
				if len(datapack) != 0:
					return True
				# 否则创建数据模型对象
				datapack = Datapack()
				try:
					datapack.time = datetime.datetime.now(tz=tz)
					datapack.device = Device.objects.get(device_number__exact=deviceNumber)
					datapack.hash = datapackHash
					# 数据包存储入库
					datapack.save()
				except Exception as e:
					printException(e)
					return False
				# 解析响应
				for i in range(0, dataCount):
					respData_i = responseData[i]
					# 计算数据哈希值
					dataHash = hash(
						respData_i[RespKeys.dataName] + respData_i[RespKeys.dataTime] + respData_i[RespKeys.templateId])
					# 根据哈希值检索数据
					try:
						data = Data.objects.get(hash__exact=dataHash)
					# 	若不存在已有的数据,则创建数据数据模型对象
					except Data.DoesNotExist:
						data = Data()

					data.unit = respData_i[RespKeys.unit]
					data.name = respData_i[RespKeys.dataName]
					data.value = respData_i[RespKeys.value]
					data.time = str2datetime(respData_i[RespKeys.dataTime])
					data.hash = dataHash
					data.datapack = datapack

					try:
						data.device = Device.objects.get(device_number__exact=deviceNumber)
						# 数据存储入库
						data.save()
					except Data.DoesNotExist as e:
						printException(e)
				return True
		except Exception as e:
			printException(e)
			return False
